/*
 * @Description:
 * @Author: Evan.Zhang
 * @Date: 2022-07-08 12:02:34
 * @LastEditTime: 2022-07-09 15:59:56
 * @LastEditors: Evan.Zhang
 * @Reference:
 */

import Methods from "./methods/index"

export default function preParser () {
  return {
    name: 'rollup-plugins:preParser',
    renderChunk(code) {
      return parseCode(code);
    },
  };
}

// 受支持的预处理方法
const supportedMethods = Methods;

// 插件解析标志
const FLAG_TAGS = "@pre-parser:"
// 插件要求
const FLAG_TAGS_RULES = new RegExp(`/^.*(${FLAG_TAGS}).*$/gs`);
// 受支持的预处理方法Keys
const supportedMethodsKeys = Object.keys(supportedMethods);
// 代码池处理指针
let ParserCursor = 0


/**
 * @description: 文档符合本插件要求
 * @return {*}
 * @param {*} code
 */
function codeHasHooks(code = "") {
  return FLAG_TAGS_RULES.test(code);
}


/**
 * @description: 解析代码
 * @return {*}
 * @param {*} code
 */
async function parseCode(code) {
  // 不符合直接返回
  if (codeHasHooks(code)) return code;
  const CODE_LINE_LIST = code.split("\n");
  const CODE_COLLECTION_LIST = []
  ParserCursor = 0;
  // 遍历查找转译的语句
  do {
    const LINE_CODE = CODE_LINE_LIST[ParserCursor];
    if (!LINE_CODE.includes(FLAG_TAGS)) {
      // 不需要解析
      CODE_COLLECTION_LIST.push(LINE_CODE);
    } else {
      // 需要解析,并保存
      const parsedCode = await parseCommandAndExecuteItSync(LINE_CODE,CODE_LINE_LIST,ParserCursor);
      CODE_COLLECTION_LIST.push(parsedCode);
    }
  } while (++ParserCursor < CODE_LINE_LIST.length)
  // 还原
  return CODE_COLLECTION_LIST.join("\n");
}



/**
 * @description: 解析并执行预处理方法
 * @return {*}
 * @param {*} codeLine:含预处理方法的代码行
 * @param {*} codePool:代码池
 * @param {*} poolIdx:代码池索引
 */
async function parseCommandAndExecuteItSync(codeLine,codePool,poolIdx) {
  const CommandPipeLine = parseCommandFromString(codeLine)
  const code = await executionCommandPipeLineSync(CommandPipeLine,codePool,poolIdx)
  return code;
}

/**
 * @description: 解析出受支持的命令管道
 * @return {*}
 * @param {*} includeCommandString
 */
function parseCommandFromString(includeCommandString) {
  // 过滤受支持的命令管道
  const CommandPipeLine = includeCommandString.split(":").filter(
    virMethodKey => supportedMethodsKeys.some(
      // 预处理命令是否受支持
      key => virMethodKey.includes(key)
    )
  ).map(
    // 转换为命令
    e => parseCommandString(e)
  );
  return CommandPipeLine;
}


function parseCommandString(command) {
  command = command.replace(")", '')
    .replaceAll("'",'"')
    .split("(")
    .filter(e=>e!=="");
  command[0] = `"${command[0]}"`
  const commandLength = command.length
  if ( commandLength!== 1) {
    command = `[${command.join(",")}]`
  } else {
    command = `[${command}]`
  }
  return JSON.parse(command)
}

/**
 * @description: 执行命令管道并返回执行结果
 * @return {*}
 * @param {*} CommandPipeLine:命令管道
 * @param {*} codePool:代码池
 * @param {*} poolIdx:代码池索引
 */
async function executionCommandPipeLineSync(CommandPipeLine, codePool, poolIdx) {
  let code = ""
  do {
    const command = CommandPipeLine.shift();
    if(!command) continue;
    code = await executeCommandSync(command,codePool,poolIdx,code);
  }while (CommandPipeLine.length);
  return code;
}

/**
 * @description: 执行命令
 * @return {*}
 * @param {*} CommandPipeLine:命令管道
 * @param {*} codePool:代码池
 * @param {*} poolIdx:代码池索引
 * @param {*} code:代码
 */
async function executeCommandSync(command, codePool, poolIdx, code) {
  const option = {
    args:command.slice(1),
    pool: codePool,
    poolIdx,
    pipeValue: code
  }
  let result = ""
  console.log(" Execute Command >>>",command);
  result = await supportedMethods[command[0]](option);
  return result;
}